package co.edu.uniquindio.mundo;

import java.util.ArrayList;
import java.util.List;

import javax.swing.JOptionPane;





import co.edu.uniquindio.analizadorLexico.SimboloLexico;

/**
 * 
 * Esta clase es la encargada de realizar todo 
 * el analisis sintatico, aca se encuentran todos los
 * metodos predicados
 * 
 * @author juanito
 * @version 1.0
 *
 */
public class AnalizadorSintactico {

	/**
	 * Atributo que representa la unidad de 
	 * compilacion
	 */
	private UnidadDeCompilacion unidadDeCompilacion;
	
	/**
	 * Atributo que guarda el token acutal
	 * del analisis
	 */
	private SimboloLexico tokenActual;
	
	/**
	 * Atributo que guarda 
	 * la posicion actual del analisis
	 */
	int posActual;
	
	/**
	 * lista donde estan almacenados todos
	 * los tokens 
	 * 
	 */
	List<SimboloLexico> listaSimbolos;

	/**
	 * Metodo constructor que permite 
	 * inicializar los listas y la unidad
	 * de compilacion
	 * 
	 */
	public AnalizadorSintactico() {
		listaSimbolos = new ArrayList<SimboloLexico>();
		
		posActual=0;
		
		//unidadDeCompilacion = esUnidadDeCompilacion();

	}

	/**
	 * Metodo que permite pasar al siguiente
	 * token
	 * 
	 */
	public void sigteToken() {
		
	
			posActual++;
			tokenActual=listaSimbolos.get(posActual);
		

	}

	/**
	 * Metodo que permite verificar si la sentencia
	 * es una unidad de compilacion correcta
	 * 
	 * @return Unidad de compilacion
	 */
	public UnidadDeCompilacion esUnidadDeCompilacion() {
		String ruta = "";
		DeclaracionDeClase declaracionDeClase = esDeclaracionDeClase();

		return new UnidadDeCompilacion(declaracionDeClase, ruta);
	}

	/**
	 * Meotodo que permite verficar si la sentencia
	 * es una declaracion de clase valida
	 * 
	 * @return DeclaracionDeClase, en caso de ser verdadera
	 * 			de lo contrario null
	 */
	public DeclaracionDeClase esDeclaracionDeClase() {
		String idClase;
		
		System.out.println("a"+tokenActual.getLexema());
		if (tokenActual.getLexema().equals("<CLASS>")) {
			sigteToken();
				System.out.println(tokenActual.getToken());
			if (tokenActual.getToken().equals("Identificador [Clase]")) {
				
				idClase = tokenActual.getLexema();
				
				BloqueVariable bloqueVariable = esBloqueVariable();
	

				return new DeclaracionDeClase("", bloqueVariable, null, idClase);
			} else {
				
				return null;
			}
		} else {
			
			return null;
		}
	}

	

	/**
	 * Metodo que permite verificar si la 
	 * sentencia es un bloquevariables
	 * 
	 * @return BloqueVariable, si es verdadero
	 *  		de lo contrario null;
	 */
	public BloqueVariable esBloqueVariable() {
		
		List<Variable> variables = new ArrayList<Variable>();
		Variable variable = esVariable();
		while (variable != null) {

			variables.add(variable);
			variable = esVariable();
		}
		if (variables.size() > 0) {
			return new BloqueVariable(variables);
		} else {
			// manejo de error
			return null;
		}

	}

	/**
	 * Metodo que permite verificar si la sentencia
	 * es una variable validad 
	 * 
	 * @return Variable, en caso de ser verdadero
	 *			de lo contrario null 
	 */
	public Variable esVariable() {

		TipoVariable tipoVariable = esTipoVariable();
		String idVariable;
		if (tipoVariable != null) {
			sigteToken();
			System.out.println("varia "+tokenActual.getLexema());
			if (tokenActual.getToken().equals("Identificador [Variable]")) {
				idVariable = tokenActual.getToken();
				sigteToken();

				if (tokenActual.getLexema().equals(";")) {
					return new Variable(tipoVariable, idVariable);
				} else {
					// manejo de error
				}
			} else {
				// manejo de error;
				return null;
			}
		} else {
			// manejo de error
			return null;
		}
		return null;
	}

	/**
	 * Metodo que permite verificar si la sentencia
	 * es un tipo de variable valido
	 * 
	 * @return TipoVariable, en caso de ser verdadero
	 * 			de lo contrario null
	 */
	public TipoVariable esTipoVariable() {
		System.out.println("tipo variable"+tokenActual.getToken());
		if (tokenActual.getToken().equals("P. R. INT")
				|| tokenActual.getLexema().equals("Cadena")) {
			boolean tipo = true;
			return new TipoVariable(tipo);
		}
		return null;
	}
	
	/**
	 * Metodo que permite acceder a la
	 * lista de simbolos
	 * 
	 * @return listaSimbolos
	 */
	public List<SimboloLexico> getListaSimbolos() {
		return listaSimbolos;
	}

	
	/**
	 * Metodo que permite modificar la lista de 
	 * simbolos
	 * 
	 * @param listaSimbolos
	 */
	public void setListaSimbolos(ArrayList<SimboloLexico> listaSimbolos) {
		tokenActual=listaSimbolos.get(0);
		this.listaSimbolos = listaSimbolos;
	}
}
